<template>
  <el-dialog
    title="图片裁剪"
    v-model="dialogVisible"
    draggable
    :close-on-click-modal="false"
    :modal-append-to-body="false"
    width="50%"
    center
  >
    <VueCropper
      ref="cropperRef"
      :img="options.img"
      :info="true"
      :info-true="options.infoTrue"
      :auto-crop="options.autoCrop"
      :fixed-box="options.fixedBox"
      :can-move="options.canMoveBox"
      :can-scale="options.canScale"
      :fixed-number="options.fixedNumber"
      :fixed="options.fixed"
      :full="options.full"
      :center-box="options.centerBox"
    >
    </VueCropper>

    <div style="text-align: center; margin-top: 20px">
      <el-button type="" @click="refreshCrop">重置</el-button>
      <el-button type="primary" @click="onConfirm"> 裁剪 </el-button>
    </div>
  </el-dialog>
</template>

<script lang="ts" setup>
import { ref, reactive } from 'vue'
// 需要引入的库
import 'vue-cropper/dist/index.css'
import { VueCropper } from 'vue-cropper'
import { uploadfile } from '@/apis/upload.js'
import type { ElMessage, ElMessageBox } from 'element-plus'

// 裁剪组件需要使用到的参数
// interface Options {
//   img: string | ArrayBuffer | null // 裁剪图片的地址
//   info: true // 裁剪框的大小信息
//   outputSize: number // 裁剪生成图片的质量 [1至0.1]
//   outputType: string // 裁剪生成图片的格式
//   canScale: boolean // 图片是否允许滚轮缩放
//   autoCrop: boolean // 是否默认生成截图框
//   autoCropWidth: number // 默认生成截图框宽度
//   autoCropHeight: number // 默认生成截图框高度
//   fixedBox: boolean // 固定截图框大小 不允许改变
//   fixed: boolean // 是否开启截图框宽高固定比例
//   fixedNumber: Array<number> // 截图框的宽高比例  需要配合centerBox一起使用才能生效
//   full: boolean // 是否输出原图比例的截图
//   canMoveBox: boolean // 截图框能否拖动
//   original: boolean // 上传图片按照原始比例渲染
//   centerBox: boolean // 截图框是否被限制在图片里面
//   infoTrue: boolean // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
//   accept: string // 上传允许的格式
// }

let dialogVisible = ref(false)

// 裁剪组件需要使用到的参数
let options = reactive({
  img: '', // 需要剪裁的图片
  autoCrop: true, // 是否默认生成截图框
  autoCropWidth: 320, // 默认生成截图框的宽度
  autoCropHeight: 180, // 默认生成截图框的长度
  fixedBox: false, // 是否固定截图框的大小 不允许改变
  info: true, // 裁剪框的大小信息
  outputSize: 1, // 裁剪生成图片的质量 [1至0.1]
  outputType: 'jpg', // 裁剪生成图片的格式
  canScale: true, // 图片是否允许滚轮缩放
  fixed: true, // 是否开启截图框宽高固定比例
  fixedNumber: [16, 9], // 截图框的宽高比例 需要配合centerBox一起使用才能生效 1比1
  full: true, // 是否输出原图比例的截图
  canMoveBox: false, // 截图框能否拖动
  original: false, // 上传图片按照原始比例渲染
  centerBox: true, // 截图框是否被限制在图片里面
  infoTrue: true, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
  accept: 'image/jpeg,image/jpg,image/png,image/gif,image/x-icon'
})

function open(file) {
  options.img = URL.createObjectURL(file.raw)

  dialogVisible.value = true
}

// 裁剪组件Ref
const cropperRef = ref({})

/* 重置裁剪组件 */
const refreshCrop = () => {
  // cropperRef裁剪组件自带很多方法，可以打印看看
  cropperRef.value.refresh()
}

const emit = defineEmits(['setPicture'])

// 上传图片（点击保存按钮）
const onConfirm = () => {
  ElMessageBox.confirm('确定裁剪图片并上传裁剪后的图片吗？', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  })
    .then(() => {
      cropperRef.value.getCropData((data) => {
        const file = base64ToFile(data, 'images.jpg')

        const fileFormData = new FormData()
        fileFormData.append('file', file)

        uploadfile(fileFormData)
          .then(function (response) {
            emit('setPicture', response.url)
            ElMessage({
              type: 'success',
              message: '上传成功'
            })
            dialogVisible.value = false
          })
          .catch(function (error) {
            console.log(error)
          })
      })
    })
    .catch(() => {
      ElMessage({
        type: 'info',
        message: '取消上传'
      })
    })
}

function base64ToFile(dataUrl, filename) {
  const arr = dataUrl.split(',')
  const mime = arr[0].match(/:(.*?);/)[1]
  const bstr = atob(arr[1])
  let len = bstr.length
  const u8arr = new Uint8Array(len)
  while (len--) {
    u8arr[len] = bstr.charCodeAt(len)
  }
  return new File([u8arr], filename, { type: mime })
}

defineExpose({ open })
</script>

<style lang="scss" scoped>
.vue-cropper {
  height: 500px;
}

.cropper {
  width: 100%;
  height: 50vh;
  display: flex;
  overflow: hidden;
  .cropper_left {
    display: flex;
    flex-direction: column;
    .reupload_box {
      display: flex;
      align-items: center;
      justify-content: space-between;
      margin-top: 10px;
      .reupload_text {
        color: var(--primary-color);
        cursor: pointer;
      }
      .rotate_right {
        margin-left: 16px;
        cursor: pointer;
      }
    }
  }
  .cropper_right {
    flex: 1;
    margin-left: 44px;
    .preview_text {
      margin-bottom: 12px;
    }
  }
}
</style>